package casbintext

import (
	"fmt"
	"log"
	"net/http"

	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"github.com/gin-gonic/gin"
)

var (
	enforcer *casbin.Enforcer
)

// GetEnforcer 获取 Casbin Enforcer 实例，确保在调用前已经初始化
func GetEnforcer() *casbin.Enforcer {
	initEnforcer()

	return enforcer
}

// initEnforcer 初始化 Casbin Enforcer，确保只执行一次
func initEnforcer() {
	adapter, err := gormadapter.NewAdapter("mysql", "root:root@tcp(127.0.0.1:3306)/students?charset=utf8mb4&parseTime=True&loc=Local", true)
	if err != nil {
		log.Fatalf("创建适配器失败: %v", err)
	}

	e, err := casbin.NewEnforcer("./model.conf", adapter)
	if err != nil {
		log.Fatalf("创建执行器失败: %v", err)
	}
	//添加策略分组
	enforcer.AddGroupingPolicy("user:alice", "role:admin")

	// // 策略管理部分：添加、删除、修改和查询策略
	added, err := e.AddGroupingPolicy("group1", "data2_admin")
	if err != nil {
		log.Fatalf("添加分组策略失败: %v", err) // 如果添加分组策略失败，打印错误信息并退出程序
	}
	fmt.Println("分组策略添加成功:", added) // 打印是否成功添加分组策略

	// 增：添加策略
	// 参数1-3: 分别是主体、客体和动作
	added1, err := e.AddPolicy("王亚川", "data2", "read")
	if err != nil {
		log.Fatalf("添加策略失败: %v", err) // 如果添加策略失败，打印错误信息并退出程序
	}
	fmt.Println("策略添加成功:", added1) // 打印是否成功添加策略

	// 查：根据条件查询策略

	filteredPolicy, _ := e.GetFilteredPolicy(0, "王亚川")
	fmt.Println("策略:", filteredPolicy) // 打印过滤后的策略列表

	// 删除策略
	removed, err := e.RemovePolicy("wangyachuan", "data2", "read")
	if err != nil {
		log.Fatalf("删除策略失败: %v", err) // 如果删除策略失败，打印错误信息并退出程序
	}
	fmt.Println("策略删除成功:", removed) // 打印是否成功删除策略

}

// Casbin 是一个中间件，用于从请求查询参数中检查用户权限
func Casbin() gin.HandlerFunc {
	return func(c *gin.Context) {
		studentID := c.Query("")
		if studentID == "" {
			c.AbortWithStatusJSON(400, gin.H{"error": "需要提供Student_id"})
			return
		}
		// 提取请求的资源（URL路径）和操作（HTTP方法）
		resource := c.Request.URL.Path
		action := c.Request.Method
		// 使用 Casbin Enforcer 检查用户权限
		ok, err := GetEnforcer().Enforce(studentID, resource, action)
		if err != nil {
			c.AbortWithStatusJSON(500, gin.H{"error": "内部服务器错误"})
			log.Printf("执行Casbin策略时出错: %v", err)
			return
		}
		if !ok {
			c.AbortWithStatusJSON(403, gin.H{"error": "您没有权限执行此操作"})
			log.Printf("用户 %s 没有权限访问资源 %s, 执行操作 %s", studentID, resource, action)
			return
		}
		log.Printf("用户 %s 成功访问资源 %s, 执行操作 %s", studentID, resource, action)
		c.Next() // 权限检查通过，继续处理请求
	}
}

// Middleware 是一个中间件函数，用于从HTTP请求头中检查用户（Student_id）对指定资源（URL路径）和操作（HTTP方法）的权限
func Middleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从HTTP请求头中获取用户ID（Student_id）
		sub := "王亚川"
		// 如果用户ID为空，则中止请求并返回400错误
		if sub == "" {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "需要提供Student_id(请求头)"})
			return
		}

		// 获取请求的资源路径（URL路径）
		obj := "data1"
		// 获取请求的操作（HTTP方法）
		act := "read"
		// 调用GetEnforcer函数来获取Casbin的Enforcer实例，并检查用户是否有权限执行操作
		ok, err := GetEnforcer().Enforce(sub, obj, act)
		fmt.Println("1")
		if err != nil {
			// 如果检查权限时出错，则中止请求并返回500错误
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "内部服务器错误"})
			log.Printf("执行Casbin策略时出错: %v", err)
			return
		}
		fmt.Println("2")

		// 如果用户没有权限执行操作
		if !ok {
			// 则中止请求并返回403错误
			c.AbortWithStatus(http.StatusForbidden)
			log.Printf("用户 %s 没有权限访问资源 %s, 执行操作 %s", sub, obj, act)
			return
		}
		if ok {
			c.JSON(200, gin.H{"msg": "权限通过"})

		}
		fmt.Println("3")

		// 权限检查通过，继续处理请求
		c.Next()

	}
}
